﻿/*======================================================================
== Copyright : BlueCurve (c)
== Licence   : Gnu/GPL v2.x
== Author    : Teddy Albina
== Email     : bluecurveteam@gmail.com
== Web site  : http://www.codeplex.com/BlueCurve
========================================================================*/
using System;
using System.IO;
using HtmlAgilityPack;

namespace BlueCurve.Common
{
    /// <summary>
    /// Fournit des fonctions pour la conversion
    /// de fichiers html en fichier texte
    /// </summary>
    public class HTML2Text : CommonFunctions
    {
        /// <summary>
        /// Read document
        /// Convertie un fichier html en texte
        /// à partie de son chemin de fichier
        /// </summary>
        /// <param name="path">Chemin d'accès du fichie</param>
        /// <returns>string</returns>
        public string ConvertHtml2TextFromFilePath(string path)
        {
            try
            {
                HtmlDocument doc = new HtmlDocument();
                doc.Load(path);
                StringWriter sw = new StringWriter();
                ConvertTo(doc.DocumentNode, sw);
                sw.Flush();
                return sw.ToString();
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// Convert from html string
        /// Convertie un document html en texte à partir de son contenu
        /// </summary>
        /// <param name="html">Contenu du document</param>
        /// <returns>string</returns>
        public string ConvertHtml2TextFromHtmlString(ref string html)
        {
            try
            {
                string data = null;
                HtmlDocument doc = new HtmlDocument();
                doc.LoadHtml(html);

                using (StringWriter writer = new StringWriter())
                {
                    this.ConvertTo(doc.DocumentNode, writer);
                    writer.Flush();
                    data = writer.ToString();
                    writer.Close();
                }

                return data;
            }
            catch
            {
                return null;
            }
        }
        
        private void ConvertContentTo(HtmlNode node, TextWriter outText)
        {
            foreach (HtmlNode subnode in node.ChildNodes)
            {
                ConvertTo(subnode, outText);
            }
        }
        
        /// <summary>
        /// Convertie un document html en texte
        /// </summary>
        /// <param name="node">Objet HtmlNode</param>
        /// <param name="outText">Objet TextWriter</param>
        private void ConvertTo(HtmlNode node, TextWriter outText)
        {
            try
            {
                string html;
                switch (node.NodeType)
                {
                    case HtmlNodeType.Comment:
                        // don't output comments
                        break;

                    case HtmlNodeType.Document:
                        ConvertContentTo(node, outText);
                        break;

                    case HtmlNodeType.Text:
                        // script and style must not be output
                        string parentName = node.ParentNode.Name;
                        /*
                        if ((parentName == "javascript") || (parentName == "script") || (parentName == "style") || (parentName == "vbscript"))
                            break;*/

                        if ((parentName.Equals("javascript", StringComparison.InvariantCultureIgnoreCase)) || (parentName.Equals("script", StringComparison.InvariantCultureIgnoreCase)) ||
                            (parentName.Equals("style", StringComparison.InvariantCultureIgnoreCase)) || (parentName.Equals("vbscript", StringComparison.InvariantCultureIgnoreCase)))
                            break;

                        // get text
                        html = ((HtmlTextNode)node).Text;

                        // is it in fact a special closing node output as text?
                        if (HtmlNode.IsOverlappedClosingElement(html))
                            break;

                        // check the text is meaningful and not a bunch of whitespaces
                        if (html.Trim().Length > 0)
                            outText.Write(HtmlEntity.DeEntitize(html));
                        break;

                    case HtmlNodeType.Element:
                        switch (node.Name)
                        {
                            case "br":
                            case "ul":
                            case "li":
                            case "div":
                            case "form":
                            case "ol":
                            case "object":
                            case "field":
                            case "fieldset":
                                outText.Write(" ");
                                break;
                            case "p":
                            case "hr":
                            case "span":
                            case "blockquote":
                                outText.Write("\r\n");
                                break;
                        }

                        if (node.HasChildNodes)
                        {
                            ConvertContentTo(node, outText);
                        }
                        break;
                }
            }
            catch
            {

            }
        }
    }
}
